package main

import (
    "bytes"
    "context"
    "encoding/json"
    "flag"
    "fmt"
    "io/ioutil"
    "net"
    "net/http"
    "os"
    "strings"
)

type TaskRequest struct {
    TaskType     string            `json:"task_type"`
    Command      string            `json:"command,omitempty"`
    ScriptURL    string            `json:"script_url,omitempty"`
    Interpreter  string            `json:"interpreter"`
    Env          map[string]string `json:"env,omitempty"`
    Mode         string            `json:"mode"`
    TimeoutSec   int               `json:"timeout"`
    SyncTimeout  int               `json:"sync_timeout,omitempty"`
    AsyncTimeout int               `json:"async_timeout,omitempty"`
    CallbackURL  string            `json:"callback"`
    TaskID       string            `json:"task_id"`
}

func main() {
    sock        := flag.String("sock", "/var/run/supervisor.sock", "unix socket path")
    taskType    := flag.String("type", "command", "command|script")
    command     := flag.String("command", "", "command to exec")
    scriptURL   := flag.String("script-url", "", "script URL to download")
    interpreter := flag.String("interpreter", "/bin/bash", "interpreter")
    envs        := flag.String("env", "", "KEY=VAL,KEY2=VAL2")
    mode        := flag.String("mode", "auto", "sync|async|auto")
    timeout     := flag.Int("timeout", 1, "auto timeout seconds")
    syncto      := flag.Int("sync-timeout", 300, "sync mode timeout seconds")
    asyncto     := flag.Int("async-timeout", 86400, "async mode timeout seconds")
    callback    := flag.String("callback", "", "callback URL for async")
    taskID      := flag.String("task-id", "", "unique task ID")
    flag.Parse()

    if *taskType!="command" && *taskType!="script" {
        fmt.Fprintln(os.Stderr,"-type must be command or script"); os.Exit(1)
    }
    if *taskType=="command" && *command=="" {
        fmt.Fprintln(os.Stderr,"-command required"); os.Exit(1)
    }
    if *taskType=="script" && *scriptURL=="" {
        fmt.Fprintln(os.Stderr,"-script-url required"); os.Exit(1)
    }
    if (*mode=="async"||*mode=="auto") && *callback=="" {
        fmt.Fprintln(os.Stderr,"async/auto need -callback"); os.Exit(1)
    }
    if *taskID=="" {
        fmt.Fprintln(os.Stderr,"-task-id required"); os.Exit(1)
    }

    envMap := map[string]string{}
    if *envs!="" {
        for _, kv := range strings.Split(*envs, ",") {
            p:=strings.SplitN(kv,"=",2)
            if len(p)==2 { envMap[p[0]]=p[1] }
        }
    }

    req := TaskRequest{
        TaskType:     *taskType,
        Command:      *command,
        ScriptURL:    *scriptURL,
        Interpreter:  *interpreter,
        Env:          envMap,
        Mode:         *mode,
        TimeoutSec:   *timeout,
        SyncTimeout:  *syncto,
        AsyncTimeout: *asyncto,
        CallbackURL:  *callback,
        TaskID:       *taskID,
    }
    body, _ := json.Marshal(req)

    client := &http.Client{
        Transport: &http.Transport{
            DialContext: func(_ context.Context, _, _ string) (net.Conn, error) {
                return net.Dial("unix", *sock)
            },
        },
    }
    resp, err := client.Post("http://unix/run","application/json",bytes.NewReader(body))
    if err!=nil {
        fmt.Fprintln(os.Stderr,"error:",err); os.Exit(1)
    }
    defer resp.Body.Close()
    out, _ := ioutil.ReadAll(resp.Body)
    fmt.Println(string(out))
}


